using System.Net;
using System.Net.Mail;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Notification
{
    /// <summary>
    /// 邮件发送结果
    /// </summary>
    public class EmailSendResult
    {
        public bool Success { get; set; }
        public string? MessageId { get; set; }
        public string? ErrorMessage { get; set; }
        public DateTime SentAt { get; set; }
        public string? Provider { get; set; }
    }

    /// <summary>
    /// 批量邮件发送结果
    /// </summary>
    public class EmailBatchSendResult
    {
        public int TotalCount { get; set; }
        public int SuccessCount { get; set; }
        public int FailureCount { get; set; }
        public List<EmailSendResult> Results { get; set; } = new();
        public TimeSpan TotalTime { get; set; }
    }

    /// <summary>
    /// 邮件消息模型
    /// </summary>
    public class EmailMessage
    {
        public string To { get; set; } = string.Empty;
        public string? ToName { get; set; }
        public string Subject { get; set; } = string.Empty;
        public string? HtmlBody { get; set; }
        public string? TextBody { get; set; }
        public string? From { get; set; }
        public string? FromName { get; set; }
        public List<EmailAttachment> Attachments { get; set; } = new();
        public Dictionary<string, string> Headers { get; set; } = new();
        public int Priority { get; set; } = 1; // 1=Normal, 2=High, 0=Low
    }

    /// <summary>
    /// 邮件附件
    /// </summary>
    public class EmailAttachment
    {
        public string FileName { get; set; } = string.Empty;
        public byte[] Content { get; set; } = Array.Empty<byte>();
        public string ContentType { get; set; } = "application/octet-stream";
        public bool IsInline { get; set; } = false;
        public string? ContentId { get; set; }
    }

    /// <summary>
    /// 邮件服务配置
    /// </summary>
    public class EmailServiceOptions
    {
        public const string SectionName = "EmailService";

        /// <summary>
        /// 默认提供商 (smtp, aliyun, tencent, sendgrid)
        /// </summary>
        public string DefaultProvider { get; set; } = "smtp";

        /// <summary>
        /// 是否启用故障转移
        /// </summary>
        public bool EnableFailover { get; set; } = true;

        /// <summary>
        /// 重试次数
        /// </summary>
        public int RetryCount { get; set; } = 3;

        /// <summary>
        /// 重试间隔（秒）
        /// </summary>
        public int RetryIntervalSeconds { get; set; } = 5;

        /// <summary>
        /// SMTP配置
        /// </summary>
        public SmtpSettings Smtp { get; set; } = new();

        /// <summary>
        /// 阿里云邮件推送配置
        /// </summary>
        public AliyunEmailSettings Aliyun { get; set; } = new();

        /// <summary>
        /// 腾讯云SES配置
        /// </summary>
        public TencentEmailSettings Tencent { get; set; } = new();
    }

    public class SmtpSettings
    {
        public string Host { get; set; } = string.Empty;
        public int Port { get; set; } = 587;
        public bool EnableSsl { get; set; } = true;
        public string Username { get; set; } = string.Empty;
        public string Password { get; set; } = string.Empty;
        public string FromAddress { get; set; } = string.Empty;
        public string FromName { get; set; } = string.Empty;
        public int TimeoutSeconds { get; set; } = 30;
    }

    public class AliyunEmailSettings
    {
        public string AccessKeyId { get; set; } = string.Empty;
        public string AccessKeySecret { get; set; } = string.Empty;
        public string Region { get; set; } = "cn-hangzhou";
        public string FromAddress { get; set; } = string.Empty;
        public string FromName { get; set; } = string.Empty;
    }

    public class TencentEmailSettings
    {
        public string SecretId { get; set; } = string.Empty;
        public string SecretKey { get; set; } = string.Empty;
        public string Region { get; set; } = "ap-beijing";
        public string FromAddress { get; set; } = string.Empty;
        public string FromName { get; set; } = string.Empty;
    }

    /// <summary>
    /// 邮件服务接口
    /// </summary>
    public interface IEmailService
    {
        /// <summary>
        /// 发送单个邮件
        /// </summary>
        Task<EmailSendResult> SendAsync(EmailMessage message);

        /// <summary>
        /// 使用模板发送邮件
        /// </summary>
        Task<EmailSendResult> SendTemplateAsync(string templateId, object model, string to, string? toName = null);

        /// <summary>
        /// 批量发送邮件
        /// </summary>
        Task<EmailBatchSendResult> SendBatchAsync(List<EmailMessage> messages);

        /// <summary>
        /// 测试邮件服务连接
        /// </summary>
        Task<bool> TestConnectionAsync(string? provider = null);

        /// <summary>
        /// 获取支持的提供商列表
        /// </summary>
        List<string> GetSupportedProviders();
    }

    /// <summary>
    /// 邮件提供商接口
    /// </summary>
    public interface IEmailProvider
    {
        string Name { get; }
        bool IsConfigured { get; }
        Task<EmailSendResult> SendAsync(EmailMessage message);
        Task<bool> TestConnectionAsync();
    }

    /// <summary>
    /// 企业级邮件服务实现
    /// 支持多提供商、自动故障转移、重试机制、模板渲染等功能
    /// </summary>
    public class EmailService : IEmailService
    {
        private readonly ILogger<EmailService> _logger;
        private readonly EmailServiceOptions _options;
        private readonly Dictionary<string, IEmailProvider> _providers;
        private readonly IServiceProvider _serviceProvider;

        public EmailService(
            ILogger<EmailService> logger,
            IOptions<EmailServiceOptions> options,
            IServiceProvider serviceProvider)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
            _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
            
            _providers = new Dictionary<string, IEmailProvider>();
            InitializeProviders();
        }

        /// <summary>
        /// 初始化邮件提供商
        /// </summary>
        private void InitializeProviders()
        {
            try
            {
                // SMTP提供商
                if (!string.IsNullOrEmpty(_options.Smtp.Host))
                {
                    _providers["smtp"] = new SmtpEmailProvider(_options.Smtp, _logger);
                }

                // 阿里云提供商
                if (!string.IsNullOrEmpty(_options.Aliyun.AccessKeyId))
                {
                    _providers["aliyun"] = new AliyunEmailProvider(_options.Aliyun, _logger);
                }

                // 腾讯云提供商
                if (!string.IsNullOrEmpty(_options.Tencent.SecretId))
                {
                    _providers["tencent"] = new TencentEmailProvider(_options.Tencent, _logger);
                }

                _logger.LogInformation("邮件服务初始化完成，可用提供商: {Providers}", string.Join(", ", _providers.Keys));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "初始化邮件提供商失败");
                throw;
            }
        }

        /// <summary>
        /// 发送单个邮件
        /// </summary>
        public async Task<EmailSendResult> SendAsync(EmailMessage message)
        {
            if (message == null)
                throw new ArgumentNullException(nameof(message));

            if (string.IsNullOrEmpty(message.To))
                throw new ArgumentException("收件人不能为空", nameof(message));

            if (string.IsNullOrEmpty(message.Subject))
                throw new ArgumentException("邮件主题不能为空", nameof(message));

            var startTime = DateTime.UtcNow;
            var providers = GetOrderedProviders();

            foreach (var provider in providers)
            {
                if (!provider.IsConfigured)
                {
                    _logger.LogWarning("邮件提供商 {Provider} 未正确配置，跳过", provider.Name);
                    continue;
                }

                try
                {
                    var result = await SendWithRetry(provider, message);
                    if (result.Success)
                    {
                        result.Provider = provider.Name;
                        var duration = DateTime.UtcNow - startTime;
                        
                        _logger.LogInformation(
                            "邮件发送成功 - 提供商: {Provider}, 收件人: {To}, 主题: {Subject}, 耗时: {Duration}ms",
                            provider.Name, message.To, message.Subject, duration.TotalMilliseconds);
                        
                        return result;
                    }
                    
                    _logger.LogWarning("邮件提供商 {Provider} 发送失败: {Error}", provider.Name, result.ErrorMessage);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "邮件提供商 {Provider} 发送异常", provider.Name);
                    
                    if (!_options.EnableFailover || providers.Count == 1)
                    {
                        return new EmailSendResult
                        {
                            Success = false,
                            ErrorMessage = ex.Message,
                            SentAt = DateTime.UtcNow,
                            Provider = provider.Name
                        };
                    }
                }
            }

            return new EmailSendResult
            {
                Success = false,
                ErrorMessage = "所有邮件提供商都发送失败",
                SentAt = DateTime.UtcNow
            };
        }

        /// <summary>
        /// 使用模板发送邮件
        /// </summary>
        public async Task<EmailSendResult> SendTemplateAsync(string templateId, object model, string to, string? toName = null)
        {
            if (string.IsNullOrEmpty(templateId))
                throw new ArgumentException("模板ID不能为空", nameof(templateId));

            try
            {
                // 这里应该集成模板引擎服务，暂时使用简单的字符串替换
                var template = await GetEmailTemplate(templateId);
                var renderedContent = await RenderTemplate(template, model);

                var message = new EmailMessage
                {
                    To = to,
                    ToName = toName,
                    Subject = renderedContent.Subject,
                    HtmlBody = renderedContent.HtmlBody,
                    TextBody = renderedContent.TextBody
                };

                return await SendAsync(message);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "模板邮件发送失败 - 模板ID: {TemplateId}, 收件人: {To}", templateId, to);
                return new EmailSendResult
                {
                    Success = false,
                    ErrorMessage = $"模板邮件发送失败: {ex.Message}",
                    SentAt = DateTime.UtcNow
                };
            }
        }

        /// <summary>
        /// 批量发送邮件
        /// </summary>
        public async Task<EmailBatchSendResult> SendBatchAsync(List<EmailMessage> messages)
        {
            if (messages == null || messages.Count == 0)
                throw new ArgumentException("邮件列表不能为空", nameof(messages));

            var result = new EmailBatchSendResult
            {
                TotalCount = messages.Count
            };

            var startTime = DateTime.UtcNow;
            var semaphore = new SemaphoreSlim(Environment.ProcessorCount * 2); // 控制并发数
            var tasks = messages.Select(async message =>
            {
                await semaphore.WaitAsync();
                try
                {
                    var sendResult = await SendAsync(message);
                    lock (result)
                    {
                        result.Results.Add(sendResult);
                        if (sendResult.Success)
                            result.SuccessCount++;
                        else
                            result.FailureCount++;
                    }
                }
                finally
                {
                    semaphore.Release();
                }
            });

            await Task.WhenAll(tasks);
            result.TotalTime = DateTime.UtcNow - startTime;

            _logger.LogInformation(
                "批量邮件发送完成 - 总数: {Total}, 成功: {Success}, 失败: {Failure}, 耗时: {Duration}ms",
                result.TotalCount, result.SuccessCount, result.FailureCount, result.TotalTime.TotalMilliseconds);

            return result;
        }

        /// <summary>
        /// 测试邮件服务连接
        /// </summary>
        public async Task<bool> TestConnectionAsync(string? provider = null)
        {
            try
            {
                if (!string.IsNullOrEmpty(provider))
                {
                    if (_providers.TryGetValue(provider.ToLower(), out var specificProvider))
                    {
                        return await specificProvider.TestConnectionAsync();
                    }
                    return false;
                }

                // 测试所有提供商
                var results = await Task.WhenAll(
                    _providers.Values.Select(p => p.TestConnectionAsync())
                );

                return results.Any(r => r);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "测试邮件服务连接失败");
                return false;
            }
        }

        /// <summary>
        /// 获取支持的提供商列表
        /// </summary>
        public List<string> GetSupportedProviders()
        {
            return _providers.Keys.ToList();
        }

        #region 私有方法

        /// <summary>
        /// 获取有序的提供商列表
        /// </summary>
        private List<IEmailProvider> GetOrderedProviders()
        {
            var orderedProviders = new List<IEmailProvider>();

            // 优先使用默认提供商
            if (_providers.TryGetValue(_options.DefaultProvider.ToLower(), out var defaultProvider))
            {
                orderedProviders.Add(defaultProvider);
            }

            // 添加其他提供商作为备选
            if (_options.EnableFailover)
            {
                foreach (var provider in _providers.Values)
                {
                    if (provider != defaultProvider)
                    {
                        orderedProviders.Add(provider);
                    }
                }
            }

            return orderedProviders;
        }

        /// <summary>
        /// 带重试机制的发送
        /// </summary>
        private async Task<EmailSendResult> SendWithRetry(IEmailProvider provider, EmailMessage message)
        {
            for (int attempt = 0; attempt <= _options.RetryCount; attempt++)
            {
                try
                {
                    var result = await provider.SendAsync(message);
                    if (result.Success || attempt == _options.RetryCount)
                    {
                        return result;
                    }

                    if (attempt < _options.RetryCount)
                    {
                        await Task.Delay(_options.RetryIntervalSeconds * 1000);
                    }
                }
                catch (Exception ex)
                {
                    if (attempt == _options.RetryCount)
                    {
                        return new EmailSendResult
                        {
                            Success = false,
                            ErrorMessage = ex.Message,
                            SentAt = DateTime.UtcNow
                        };
                    }

                    if (attempt < _options.RetryCount)
                    {
                        await Task.Delay(_options.RetryIntervalSeconds * 1000);
                    }
                }
            }

            return new EmailSendResult
            {
                Success = false,
                ErrorMessage = "重试次数已用完",
                SentAt = DateTime.UtcNow
            };
        }

        /// <summary>
        /// 获取邮件模板
        /// </summary>
        private async Task<EmailTemplate> GetEmailTemplate(string templateId)
        {
            // 这里应该从数据库或文件系统获取模板
            // 暂时返回一个简单的模板
            await Task.CompletedTask;
            
            return new EmailTemplate
            {
                Id = templateId,
                Subject = "系统通知 - {Title}",
                HtmlBody = "<h1>{Title}</h1><p>{Content}</p>",
                TextBody = "{Title}\n\n{Content}"
            };
        }

        /// <summary>
        /// 渲染模板
        /// </summary>
        private async Task<RenderedTemplate> RenderTemplate(EmailTemplate template, object model)
        {
            await Task.CompletedTask;
            
            // 简单的字符串替换，实际应该使用Razor或其他模板引擎
            var properties = model.GetType().GetProperties();
            var result = new RenderedTemplate
            {
                Subject = template.Subject ?? string.Empty,
                HtmlBody = template.HtmlBody ?? string.Empty,
                TextBody = template.TextBody ?? string.Empty
            };

            foreach (var prop in properties)
            {
                var value = prop.GetValue(model)?.ToString() ?? "";
                var placeholder = "{" + prop.Name + "}";
                
                result.Subject = (result.Subject ?? string.Empty).Replace(placeholder, value);
                result.HtmlBody = (result.HtmlBody ?? string.Empty).Replace(placeholder, value);
                result.TextBody = (result.TextBody ?? string.Empty).Replace(placeholder, value);
            }

            return result;
        }

        #endregion
    }

    #region 内部模型

    internal class EmailTemplate
    {
        public string Id { get; set; } = string.Empty;
        public string Subject { get; set; } = string.Empty;
        public string? HtmlBody { get; set; }
        public string? TextBody { get; set; }
    }

    internal class RenderedTemplate
    {
        public string Subject { get; set; } = string.Empty;
        public string? HtmlBody { get; set; }
        public string? TextBody { get; set; }
    }

    #endregion
}
